'''
项目名称：产业园区管理运营平台
文件名称：业务数据生成脚本
@Author: 王旭
@Contact: 1643959780@qq.com
@Created: 2025/06/28
@Version: V1.2

@Description:
本脚本为产业园区管理运营平台生成核心业务数据，包含租赁申请与合同。
它完整覆盖了从"意向申请"到"正式签约"的业务流程。
依赖于 `init_personnel.py` 和 `init_assets.py` 生成的基础数据。
主要功能包括：
1. 创建房源和车位的租赁申请。
2. 基于审核通过的申请创建房源租赁合同和车位租赁合同。
3. 更新相关单元的状态为"已租"。
4. 合同金额基于资产的租金单价进行计算，确保数据真实性。

@Modifications:
- V1.0 (2025/06/28): 将 `init_applications.py` 合并至此脚本，实现申请与合同生成的统一。
- V1.1 (2025/06/28): 修正合同金额计算逻辑，使其基于单元的 rental_price 字段。
- V1.2 (2025/06/28): 实现整合租房/车位申请，实现合同数据的生成。
'''

import os
import sys
import django
import random
import datetime
from django.utils import timezone
from faker import Faker
from dateutil.relativedelta import relativedelta

# --- Start: 动态添加项目根目录到 sys.path ---
# 获取当前脚本文件(init_business.py)的绝对路径
current_script_path = os.path.abspath(__file__)
# 获取脚本所在的目录 (script/)
script_dir = os.path.dirname(current_script_path)
# 获取项目根目录 (back/)，即 script 目录的上级目录
project_root = os.path.dirname(script_dir)
# 将项目根目录添加到 Python 模块搜索路径中
sys.path.append(project_root)
# --- End: 动态添加项目根目录到 sys.path ---

from django.db import transaction
from users.models import Company, User, CompanyEmployeeProfile
from assets.models import Unit, Vehicle
from services.models import Contract, LeasingApplicationService, ParkingSpaceLeasingService

# 初始化Faker
fake = Faker('zh_CN')

# 配置参数
CONFIG = {
    "applications": {
        "leasing_count": 50,  # 生成的房源租赁申请数量
        "parking_count": 100, # 生成的车位租赁申请数量
    }
}

def clear_old_business_data():
    """清除旧的业务数据（申请与合同）"""
    print("--- 正在清除旧的业务数据... ---")
    # 必须先删除子表（申请），再删除父表（合同）
    LeasingApplicationService.objects.all().delete()
    ParkingSpaceLeasingService.objects.all().delete()
    Contract.objects.all().delete()
    
    # 将所有已租/已售的单元恢复为空置，以便重新分配
    # 注意：这个操作依赖于上层数据（如合同）已被清除
    Unit.objects.filter(status__in=['已租', '已售']).update(status='空置')
    print("旧合同和申请数据已清除，相关单元状态已重置为空置。")


@transaction.atomic
def create_business_data():
    """创建所有业务数据（申请+合同）"""
    print("--- 开始创建业务数据 (申请与合同) ---")

    try:
        # 定义全局的甲方（园区运营方）
        # 确保系统中至少有一个公司作为园区运营方
        party_a_company = Company.objects.first()
        if not party_a_company:
            print("错误：系统中没有任何公司，无法指定合同甲方。请先运行 init_personnel.py。")
            return

        print(f"*** 合同甲方（园区运营方）已指定为: {party_a_company.company_name} ***")

        # 1. 创建租赁申请
        create_leasing_applications()
        create_parking_space_applications()

        # 2. 根据申请创建合同, 传入固定的甲方
        create_rental_contracts(party_a_company)
        create_parking_contracts(party_a_company)

        print("\n业务数据 (申请与合同) 生成完成！")
        print_statistics()
    except Exception as e:
        print(f"\n!!! 数据生成过程中发生错误，事务将回滚 !!!")
        print(f"错误详情: {e}")
        import traceback
        traceback.print_exc()

def create_leasing_applications():
    """创建房源租赁申请"""
    print("\n创建房源租赁申请...")
    # 找出所有空置的、可租赁的单元（非车位）
    available_units = list(Unit.objects.filter(status='空置').exclude(unit_type='车位'))
    # 找出所有公司的法人代表作为潜在申请人
    potential_applicants = list(CompanyEmployeeProfile.objects.filter(is_legal_representative=True).select_related('user', 'company'))
    
    if not available_units or not potential_applicants:
        print("警告：没有足够的空置房源或申请人来创建租赁申请。")
        return

    num_to_create = min(len(available_units), len(potential_applicants), CONFIG['applications']['leasing_count'])
    created_count = 0
    
    random.shuffle(available_units)
    random.shuffle(potential_applicants)

    for i in range(num_to_create):
        unit = available_units[i]
        applicant_profile = potential_applicants[i]
        
        # 增加随机申请状态，模拟真实业务流程
        # 权重: 60%审核通过, 15%待审核, 15%审核中, 10%审核驳回
        application_status = random.choices(
            ['审核通过', '待审核', '审核中', '审核驳回'], 
            weights=[60, 15, 15, 10], 
            k=1
        )[0]
        
        LeasingApplicationService.objects.create(
            applicant_user=applicant_profile.user,
            company=applicant_profile.company,
            unit=unit,
            application_time=timezone.now(),
            expected_start_date=fake.date_between(start_date='-1M', end_date='+1M'),
            expected_duration=random.choice([12, 24, 36]), # 1-3年
            status=application_status,
            created_at=timezone.now(),
            updated_at=timezone.now()
        )
        created_count += 1
    print(f"成功创建 {created_count} 条房源租赁申请。")


def create_parking_space_applications():
    """创建车位租赁申请"""
    print("\n创建车位租赁申请...")
    # 找出所有空置的车位
    available_spaces = list(Unit.objects.filter(status='空置', unit_type='车位'))
    # 找出所有名下有车的用户
    potential_applicants = list(Vehicle.objects.filter(user__isnull=False).select_related('user'))

    if not available_spaces or not potential_applicants:
        print("警告：没有足够的空置车位或申请人来创建车位租赁申请。")
        return

    num_to_create = min(len(available_spaces), len(potential_applicants), CONFIG['applications']['parking_count'])
    created_count = 0
    
    random.shuffle(available_spaces)
    random.shuffle(potential_applicants)

    for i in range(num_to_create):
        space = available_spaces[i]
        vehicle_owner = potential_applicants[i]

        # 增加随机申请状态
        application_status = random.choices(
            ['审核通过', '待审核', '审核中', '审核驳回'], 
            weights=[60, 15, 15, 10], 
            k=1
        )[0]

        ParkingSpaceLeasingService.objects.create(
            applicant_user=vehicle_owner.user,
            unit=space,
            vehicle=vehicle_owner,
            application_time=timezone.now(),
            expected_start_date=fake.date_between(start_date='-1M', end_date='+1M'),
            expected_duration=12, # 车位一般租一年
            status=application_status,
            created_at=timezone.now(),
            updated_at=timezone.now()
        )
        created_count += 1
    print(f"成功创建 {created_count} 条车位租赁申请。")


def create_rental_contracts(party_a_company):
    """根据已批准的房源租赁申请创建合同"""
    print("\n开始根据租赁申请创建房源合同...")
    
    # 核心逻辑：只为"审核通过"且未生成过合同的申请创建合同
    applications = LeasingApplicationService.objects.filter(status='审核通过', contract__isnull=True)
    
    if not applications:
        print("没有找到待处理的房源租赁申请。")
        return

    created_count = 0
    newly_created_contracts = []

    for app in applications:
        now = timezone.now()
        start_date = app.expected_start_date
        end_date = start_date + relativedelta(months=app.expected_duration)
        total_amount = app.unit.rental_price * app.unit.actual_area * app.expected_duration
        
        # 步骤1：创建合同，初始状态统一为"未生效"
        contract = Contract.objects.create(
            contract_number=f"CT-RENT-{now.year}{now.month:02d}-{app.unit.unit_id:04d}",
            contract_name=f"{app.company.company_name} 的 {app.unit.unit_number} 租赁合同",
            contract_type='房源租赁',
            company=app.company,  # 乙方是申请公司
            user=None,            # 乙方是公司，所以user为None
            party_b="智慧产业园管理方", # 甲方是园区运营公司
            unit=app.unit,
            contract_amount=round(total_amount, 2),
            payment_cycle=random.choice(['月付', '季付', '年付']),
            start_date=start_date,
            end_date=end_date,
            sign_date=None,  # 初始创建时无签订日期
            status='未生效', 
            created_at=now,
            updated_at=now
        )
        newly_created_contracts.append(contract)
        
        # 步骤2：回写申请单的关联合同ID
        app.contract = contract
        app.save()
        created_count += 1
    
    print(f"成功创建 {created_count} 份状态为'未生效'的房源租赁合同。")

    # 步骤3：模拟合同审核流程，将一部分合同置为"生效中"
    contracts_to_activate = random.sample(
        newly_created_contracts, 
        k=int(len(newly_created_contracts) * 0.7) # 激活70%
    )
    activated_count = 0
    for contract in contracts_to_activate:
        contract.status = '生效中'
        contract.sign_date = contract.start_date - relativedelta(days=random.randint(5, 15))
        contract.save()
        
        # 状态联动：只有"生效中"的合同才占用资产
        contract.unit.status = '已租'
        contract.unit.save()
        activated_count += 1
    
    print(f"模拟审核通过，将 {activated_count} 份合同的状态更新为'生效中'，并关联资产。")


def create_parking_contracts(party_a_company):
    """根据已批准的车位租赁申请创建合同"""
    print("\n开始根据租赁申请创建车位合同...")

    applications = ParkingSpaceLeasingService.objects.filter(status='审核通过', contract__isnull=True)

    if not applications:
        print("没有找到待处理的车位租赁申请。")
        return

    created_count = 0
    newly_created_contracts = []

    for app in applications:
        now = timezone.now()
        start_date = app.expected_start_date
        end_date = start_date + relativedelta(months=app.expected_duration)
        total_amount = app.unit.rental_price * app.expected_duration
        
        # 步骤1：创建合同，初始状态统一为"未生效"
        contract = Contract.objects.create(
            contract_number=f"CT-PARK-{now.year}{now.month:02d}-{app.unit.unit_id:04d}",
            contract_name=f"{app.applicant_user.companyemployeeprofile.name} 的 {app.unit.unit_number} 车位租赁合同",
            contract_type='车位租赁',
            company=None,               # 乙方不是公司
            user=app.applicant_user,    # 乙方是申请人
            party_b="智慧产业园管理方", # 甲方是园区运营公司
            unit=app.unit,
            vehicle=app.vehicle,
            contract_amount=round(total_amount, 2),
            payment_cycle='年付',
            start_date=start_date,
            end_date=end_date,
            sign_date=None, # 初始创建时无签订日期
            status='未生效',
            created_at=now,
            updated_at=now
        )
        newly_created_contracts.append(contract)

        # 步骤2：回写申请单的关联合同ID
        app.contract = contract
        app.save()
        created_count += 1
    
    print(f"成功创建 {created_count} 份状态为'未生效'的车位租赁合同。")

    # 步骤3：模拟合同审核流程
    contracts_to_activate = random.sample(
        newly_created_contracts, 
        k=int(len(newly_created_contracts) * 0.7) # 激活70%
    )
    activated_count = 0
    for contract in contracts_to_activate:
        contract.status = '生效中'
        contract.sign_date = contract.start_date - relativedelta(days=random.randint(1, 7))
        contract.save()

        # 状态联动
        contract.unit.status = '已租'
        contract.unit.save()
        activated_count += 1
        
    print(f"模拟审核通过，将 {activated_count} 份合同的状态更新为'生效中'，并关联资产。")


def print_statistics():
    """打印数据统计信息"""
    print("\n=== 业务数据统计 ===")
    
    # 申请统计
    leasing_app_count = LeasingApplicationService.objects.count()
    parking_app_count = ParkingSpaceLeasingService.objects.count()
    print(f"租赁申请总数: {leasing_app_count + parking_app_count}")
    print(f"  - 房源租赁申请: {leasing_app_count}份")
    print(f"  - 车位租赁申请: {parking_app_count}份")

    # 合同统计
    total_contracts = Contract.objects.count()
    rental_contracts = Contract.objects.filter(contract_type='房源租赁').count()
    parking_contracts = Contract.objects.filter(contract_type='车位租赁').count()
    
    print(f"\n合同总数: {total_contracts}")
    print(f"  - 房源租赁合同: {rental_contracts}份")
    print(f"  - 车位租赁合同: {parking_contracts}份")
    
    rented_units = Unit.objects.filter(status='已租').count()
    print(f"\n已租单元总数: {rented_units}")

if __name__ == "__main__":
    clear_old_business_data()
    create_business_data() 